const db = require('../../mysql/index')
const multer = require("multer")
const path = require('path')
const multiparty = require('multiparty')
const fs = require('fs');
const mv = require('mv');
//获取用户账号函数
const getUserAccount = (e) => {
    db.query('select * from bilibili_personal where account=?', e, (err, restult) => {
        account = restult[0].account
    })
}
exports.getinfo = (req, res) => {
    let user
    req.query.up ? user = req.query.up : user = req.user.username
    let self = false
    db.query('select * from bilibili_personal where account=?', user, (err, restult) => {
        db.query('select id from bilibili_videos where up=?', user, (err, newr_estult) => {
            if (err) return res.send({
                status: 1,
                mes: err.message
            })
            if (req.user) {
                req.user.id == restult[0].id ? self = true : self = false
            }
            if (restult.length === 0) return
            delete restult[0].password
            restult[0].active = newr_estult.length
            restult[0].about = emojiDecode(restult[0].about)
            restult[0].self = self
            res.send({
                status: 0,
                mes: restult
            })
        })
    })
}
exports.getProfile = (req, res) => {
    db.query('select profile from bilibili_personal where id=?', req.user.id, (err, restult) => {
        if (err) return res.send({
            status: 1,
            mes: err.message
        })
        res.send({
            status: 0,
            mes: restult
        })
    })
}

// 已弃用这个接口
exports.upload_profile = (req, res) => {
    db.query('UPDATE bilibili_personal SET profile=? where account=? ', [req.body.profile, req.user.username], (err, restult) => {
        if (err) return res.send({
            status: 1,
            mes: err.message
        })
        if (restult.affectedRows === 1) {
            res.send({
                status: 0,
                mes: '更新成功'
            })
        } else {
            res.send({
                status: 1,
                mes: '更新失败'
            })
        }
    })
}

let fullPath = path.join(__dirname, "../../public/profiles")
let mystorage = multer.diskStorage({
    //设置文件存储路径
    destination: (req, file, cb) => {
        cb(null, fullPath);
    },
    //设置文件存储名称  
    filename: (req, file, cb) => {
        filename = req.user.username
        cb(null, filename);
    }
})

exports.uploadFile = (req, res) => {
    //dest 值为文件存储的路径;single方法,表示上传单个文件,参数为表单数据对应的key
    let upload = multer({ storage: mystorage }).single("profile");
    upload(req, res, (err) => {
        if (err instanceof multer.MulterError) {
            console.log(err);
            return res.send({
                status: 1,
                message: '上传失败'
            })
        } else if (err) {
            return console.log(err);
        }
        else {
            return db.query('UPDATE bilibili_personal SET profile=? where account=? ', [req.file.filename, req.user.username], (err, restult) => {
                if (err) return res.send({
                    status: 1,
                    mes: err.message
                })
                if (restult.affectedRows === 1) {
                    return res.send({
                        status: 0,
                        mes: '上传成功'
                    })
                } else {
                    res.send({
                        status: 1,
                        mes: '上传失败'
                    })
                }
            })
        }
    })
}

const emojiEncode = (e) => {
    let n = /[\ud800-\udbff][\udc00-\udfff]/g;
    // let n
    // 检测utf16字符正则
    return e = e.replace(n, function (e) {
        let n, r;
        return 2 === e.length ? (n = e.charCodeAt(0), r = e.charCodeAt(1),
            "&#" + (1024 * (n - 55296) + 65536 + r - 56320) + ";") : e
    })
}


const emojiDecode = (e) => {
    let n = /&#.*?;/g; //获取数据库种16进制的数据
    //然后进行解码操作
    if (!e) return null
    return e.replace(n, function (e) {
        let n, r, t;
        return 9 == e.length ? (t = parseInt(e.match(/[0-9]+/g)), n = Math.floor((t - 65536) / 1024) +
            55296, r = (t - 65536) % 1024 + 56320, unescape("%u" + n.toString(16) + "%u" + r
                .toString(16))) : e
    })
}

exports.change = (req, res) => {
    let sex = req.body.sex
    let systemcalls = req.body.systemcall
    req.body.about_value = emojiEncode(req.body.about_value)
    switch (sex) {
        case '男':
            sex = 'man'
            break;
        case '女':
            sex = 'gril'
            break;
        case '保密':
            sex = 'secret'
            break;
        default:
            if (sex.length > 5) return res.send({
                status: 1,
                mes: '性别不能大于五个字符'
            })
            sex = req.body.sex
            break;
    }
    switch (systemcalls) {
        case 0:
            systemcalls = '他'
            break;
        case 1:
            systemcalls = '她'
            break;
        default:
            systemcalls = 'Ta'
            break;
    }
    if (req.body.username.length > 10) return res.send({
        status: 1,
        mes: '用户名不能大于十个字符'
    })

    if (req.body.about_value.length > 70) return res.send({
        status: 1,
        mes: '个性签名不能超过70个字符'
    })
    db.query('UPDATE bilibili_personal SET username=?,sex=?,about=?,system_call=? where account=? ', [req.body.username, sex, req.body.about_value, systemcalls, req.user.username], (err, restult) => {
        if (err) return res.send({
            status: 1,
            mes: err
        })
        if (restult.affectedRows === 1) {
            return res.send({
                status: 0,
                mes: '上传成功'
            })
        }
    })
}

const UPLOAD_DIR = path.join(__dirname, '../../public/videos')
exports.uploadvideo = async (req, res) => {
    const form = new multiparty.Form()
    form.parse(req, async (err, fields, files) => {
        if (err) return res.send({
            status: 1,
            mes: err,
        })
        const fileHash = fields['filehash'][0]
        const chunkhash = fields['chunkhash'][0]
        // 创建临时存放目录
        const chunkpath = path.resolve(UPLOAD_DIR, fileHash)
        if (!fs.existsSync(chunkpath)) {
            fs.mkdirSync(chunkpath)
        }
        // console.log(files['chunk'][0]);
        const oldPath = files['chunk'][0]['path']
        new Promise(solove => {
            return mv(oldPath, path.resolve(chunkpath, chunkhash), function (err) {
                if (err) {
                    console.log(err);
                }
                solove()
            })
        }).then(() => {
            res.send({
                status: 0,
                mes: '上传成功'
            })
        })
    })
}

exports.merge = async (req, res) => {
    const { fileHash, fileName, size } = req.body
    const filePath = path.resolve(UPLOAD_DIR, fileHash + path.extname(fileName))
    if (fs.existsSync(filePath)) return res.send({
        status: 0,
        mes: '上传成功'
    })
    const chunkDir = path.resolve(UPLOAD_DIR, fileHash)
    if (!fs.existsSync(chunkDir)) return res.send({
        status: 1,
        mes: '合并失败,请重新上传'
    })
    const chunkPath = fs.readdirSync(chunkDir)
    chunkPath.sort((a, b) => {
        return a.split('-')[1] - b.split('-')[1]
    })
    const list = chunkPath.map((chunkName, index) => {
        return new Promise(resolve => {
            const chunkPath = path.resolve(chunkDir, chunkName)
            const readStream = fs.createReadStream(chunkPath)
            const writeSteam = fs.createWriteStream(filePath, {
                start: index * size,
                end: (index + 1) * size
            })
            readStream.pipe(writeSteam)
            readStream.on('end', () => {
                fs.unlinkSync(chunkPath)
                resolve()
            })
        })
    })

    await Promise.all(list)
    try {
        fs.rmdirSync(chunkDir)
    } catch (error) {
        console.log('视频上传出现问题');
    }
    res.send({
        status: 0,
        mes: '合并成功'
    })
}


exports.uploadhash = (req, res) => {
    const { fileHash, fileName, fileSize } = req.body
    const filePath = path.resolve(UPLOAD_DIR, fileHash + path.extname(fileName))
    if (fileSize / (1024 * 1024) > 1024) return res.send({
        status: 1,
        have: true,
        message: '请上传小于1G的视频'
    })
    if (fs.existsSync(filePath)) return res.send({
        status: 0,
        have: true
    })
    return res.send({
        status: 0,
        have: false
    })
}
exports.lunchvideo = (req, res) => {
    let videoimage_fullPath = path.join(__dirname, "../../public/videoimages")
    //dest 值为文件存储的路径;single方法,表示上传单个文件,参数为表单数据对应的key
    // let upload = multer({ video_storage }).single("image");
    let upload = multer({ dest: videoimage_fullPath }).single("image");
    upload(req, res, async (err) => {
        if (!req.file) return res.send({
            status: 1,
            mes: '视频封面获取失败，请更换浏览器'
        })
        let { fileHash, fileName, title, about } = req.body
        about === 'null' && (about = '-')
        const last_name_regex = /[^\.]\w*$/
        const last_name = last_name_regex.exec(fileName)
        fileName = fileHash + '.' + last_name
        if (err instanceof multer.MulterError) {
            res.send({
                status: 1,
                message: err
            })
        } else if (err) {
            console.log(err);
            res.send({
                status: 1,
                message: err
            })
        }
        else {
            db.query('INSERT INTO bilibili_videos ( fileName, title, about, image, up, time,upid) VALUES (?, ?, ?, ?, ?, ?, ?)', [fileName, title, about, req.file.filename, req.user.username, Date.now(), req.user.id], (err, restult) => {
                if (err) return res.send({
                    status: 1,
                    mes: err.message
                })
                if (restult.affectedRows === 1) {
                    return res.send({
                        status: 0,
                        mes: '上传成功'
                    })
                } else {
                    res.send({
                        status: 1,
                        mes: '数据库上传失败'
                    })
                }
            })
        }
    })
}

exports.isFan = (req, res) => {
    const { account } = req.body
    let isFan = false
    db.query(`SELECT idol from bilibili_personal where id = ?`, [req.user.id], (err, myres) => {
        db.query(`SELECT id from bilibili_personal where account = ?`, [account], (err, idres) => {
            if (myres[0].idol != null) {
                let idolArr = myres[0].idol.split(',')
                if (idolArr.indexOf(String(idres[0].id)) != -1) isFan = true
            }
            res.send({
                state: 0,
                message: isFan
            })
        })
    })
}

exports.getfriends = async (req, res) => {
    const { up } = req.body
    let fansArr, idolArr, promiseListOne = [], promiseListTwo = [], newFans = [], newIdol = []
    db.query('SELECT idol,fans from bilibili_personal where account=?', [up], async (err, result) => {
        let idol = result[0].idol
        let fans = result[0].fans
        if (idol) {
            idolArr = idol.split(',')
            for (let i = 0; i < idolArr.length; i++) {
                promiseListOne.push(new Promise(resolve => {
                    db.query('SELECT username,profile,about,id,account from bilibili_personal where id=?', [idolArr[i]], (err, idolres) => {
                        if (err) return res.send({
                            status: 1,
                            message: err
                        })
                        newIdol.push(idolres[0])
                        resolve()
                    })
                })
                )
            }
        } else {
            idolArr = null
        }
        if (fans) {
            fansArr = fans.split(',')
            for (let i = 0; i < fansArr.length; i++) {
                promiseListTwo.push(new Promise(resolve => {
                    db.query('SELECT username,profile,about,id,account from bilibili_personal where id=?', [fansArr[i]], (err, fansres) => {
                        if (err) return res.send({
                            status: 1,
                            message: err
                        })
                        fansres[0].same = false
                        newFans.push(fansres[0])
                        resolve()
                    })
                })
                )
            }
        } else {
            fansArr = null
        }
        await Promise.allSettled(promiseListTwo)
        await Promise.allSettled(promiseListOne)
        let friendList = {
            idol: newIdol,
            fans: newFans
        }
        res.send({
            status: 0,
            message: friendList
        })
    })
}

exports.getfriendsWithToken = async (req, res) => {
    const { up } = req.body
    let fansArr, idolArr, promiseListOne = [], promiseListTwo = [], newFans = [], newIdol = []
    db.query('SELECT idol,fans from bilibili_personal where account=?', [up], async (err, result) => {
        let idol = result[0].idol
        let fans = result[0].fans
        if (idol) {
            idolArr = idol.split(',')
            for (let i = 0; i < idolArr.length; i++) {
                promiseListOne.push(new Promise(resolve => {
                    db.query('SELECT username,profile,about,id,account from bilibili_personal where id=?', [idolArr[i]], (err, idolres) => {
                        if (err) return res.send({
                            status: 1,
                            message: err
                        })
                        idolres[0].same = false
                        newIdol.push(idolres[0])
                        resolve()
                    })
                })
                )
            }
        } else {
            idolArr = null
        }
        if (fans) {
            fansArr = fans.split(',')
            for (let i = 0; i < fansArr.length; i++) {
                promiseListTwo.push(new Promise(resolve => {
                    db.query('SELECT username,profile,about,id,account from bilibili_personal where id=?', [fansArr[i]], (err, fansres) => {
                        if (err) return res.send({
                            status: 1,
                            message: err
                        })
                        fansres[0].same = false
                        newFans.push(fansres[0])
                        resolve()
                    })
                })
                )
            }
        } else {
            fansArr = null
        }
        await Promise.allSettled(promiseListTwo)
        await Promise.allSettled(promiseListOne)
        let MYFansArr, MyIdolArr
        let myInfo = new Promise((solve) => {
            db.query('SELECT idol,fans from bilibili_personal where id=?', [req.user.id], async (err, My_result) => {
                let Myidol = My_result[0].idol
                let Myfans = My_result[0].fans
                if (Myidol) {
                    MyIdolArr = Myidol.split(',')
                } else {
                    MyIdolArr = null
                }
                if (Myfans) {
                    MYFansArr = Myfans.split(',')
                } else {
                    MYFansArr = null
                }
                solve()
            })
        })
        await myInfo
        if (idolArr && MyIdolArr) {
            let SamePart = idolArr.filter(item => MyIdolArr.includes(item))
            for (let i = 0; i < idolArr.length; i++) {
                for (let x = 0; x < SamePart.length; x++) {
                    if (newIdol[i].id == SamePart[x]) {
                        newIdol[i].same = true
                    }
                }
            }
        }
        if (fansArr && MYFansArr) {
            let SamePart = fansArr.filter(item => MYFansArr.includes(item))
            for (let i = 0; i < idolArr.length; i++) {
                for (let x = 0; x < SamePart.length; x++) {
                    if (newFans[i].id == SamePart[x]) {
                        newFans[i].same = true
                    }
                }
            }
        }
        let friendList = {
            idol: newIdol,
            fans: newFans
        }
        res.send({
            status: 0,
            message: friendList
        })
    })
}

exports.search = async (req, res) => {
    const content = req.query.content
    let FinalResult = {
        user: [],
        video: []
    }
    const user_sql = `SELECT profile,username,account,fans,id from bilibili_personal where username like "%${content}%" `
    const video_sql = `SELECT image,title,time,upid,id from bilibili_videos where title like "%${content}%" `
    await new Promise(resolve => {
        db.query(user_sql, content, async (err, user_res) => {
            if (err) return res.send({
                status: 1,
                message: err
            })
            let promiseList = []
            let promiseListOne = []
            if (req.user) {
                for (let i = 0; i < user_res.length; i++) {
                    promiseListOne.push(new Promise(fan_resolve => {
                        db.query('SELECT fans from bilibili_personal where id=?', user_res[i].id, (err, fans_res) => {
                            if (err) return fan_resolve()
                            user_res[i].isFan = false
                            if (fans_res[0].fans) {
                                let fansList = fans_res[0].fans.split(',')
                                user_res[i].isFan = fansList.indexOf(String(req.user.id)) === -1 ? false : true
                            }
                            fan_resolve()
                        })
                    }))
                }
            }
            for (let i = 0; i < user_res.length; i++) {
                promiseList.push(new Promise(resolve => {
                    db.query('SELECT id from bilibili_videos where upid=?', user_res[i].id, async (err, video_count_res) => {
                        if (err) return resolve()
                        user_res[i].active = video_count_res.length
                        resolve()
                    })
                }))
            }
            await Promise.all(promiseList)
            await Promise.all(promiseListOne)
            resolve(FinalResult.user = user_res)
        })
    })
    await new Promise(resolve => {
        db.query(video_sql, content, async (err, video_res) => {
            if (err) return res.send({
                status: 1,
                message: err
            })
            let promiseList = []
            for (let i = 0; i < video_res.length; i++) {
                promiseList.push(new Promise(resolve => {
                    db.query('SELECT username,account from bilibili_personal where id=?', video_res[i].upid, (err, username_res) => {
                        if (err) return res.send({
                            status: 1,
                            message: err
                        })
                        video_res[i].username = username_res[0].username
                        video_res[i].account = username_res[0].account
                        resolve()
                    })
                }))
            }
            await Promise.all(promiseList)
            resolve(FinalResult.video = video_res)
        })
    })
    res.send({
        status: 0,
        message: FinalResult
    })
}

const bcrypt = require('bcryptjs') //加密密码
const svgCaptcha = require('svg-captcha');
const { query } = require('express');
const { resolve4 } = require('dns');
exports.verifyCode = (req, res) => {
    // 创建验证码
    let captcha = svgCaptcha.create({
        color: true, // 彩色
        //inverse:false,// 反转颜色
        width: 100, //  宽度
        height: 40, // 高度
        fontSize: 48, // 字体大小
        size: 4, // 验证码的长度
        noise: 3, // 干扰线条
        ignoreChars: '0oO1ilI' // 验证码字符中排除 0o1i
    })

    const code_id = bcrypt.hashSync(captcha.text.toLowerCase(), 10)
    res.send({
        status: 0,
        data: captcha.data,
        code_id
    })
    // 往session，cookie中都存入一个验证码，并且把验证码显示在页面上
}


exports.getChat = async (req, res) => {
    const { id } = req.query
    if (!id) return res.send({
        status: 1,
        message: '请输入参数'
    })
    let allchat_res = []
    await new Promise(resolve => {
        db.query('select `message`,`time` from bilibili_chat where `from`=? and `to`=?', [req.user.id, id], (err, chat_res) => {
            if (err) return res.send({
                status: 1,
                message: err
            })
            chat_res.forEach(item => {
                item.myself = true
                allchat_res.push(item)
            });
            resolve()
        })
    })
    await new Promise(resolve => {
        const emojiDecode = (e) => {
            if (!e) return null
            let n = /&#.*?;/g; //获取数据库种16进制的数据
            //然后进行解码操作
            return e.replace(n, function (e) {
                let n, r, t;
                return 9 == e.length ? (t = parseInt(e.match(/[0-9]+/g)), n = Math.floor((t - 65536) / 1024) +
                    55296, r = (t - 65536) % 1024 + 56320, unescape("%u" + n.toString(16) + "%u" + r
                        .toString(16))) : e
            })
        }
        db.query('select `message`,`time` from bilibili_chat where `from`=? and `to`=?', [id, req.user.id], (err, chat_res) => {
            if (err) return res.send({
                status: 1,
                message: err
            })
            chat_res.forEach(item => {
                item.myself = false
                allchat_res.push(item)
            });
            resolve()
        })
    })
    allchat_res.sort((a, b) => {
        return (parseInt(a.time) - parseInt(b.time))
    })
    res.send({
        status: 0,
        message: allchat_res
    })
}


exports.getChatUserInfo = (req, res) => {
    const { id } = req.query
    const sql = 'select id,username,profile from bilibili_personal where id=?'
    infoRes = {}
    db.query(sql, req.user.id, (err, my_res) => {
        if (err) return res.send({
            status: 1,
            message: err
        })
        infoRes.myInfo = my_res
        db.query(sql, id, (err, another_res) => {
            if (err) return res.send({
                status: 1,
                message: err
            })
            if (another_res.length === 0) return res.send({
                status: 1,
                message: '没找到人'
            })
            infoRes.anatherInfo = another_res
            res.send({
                status: 0,
                message: infoRes
            })
        })
    })
}

exports.getChatList = async (req, res) => {
    let ListFrom = {}
    let ListTo = {}
    await new Promise(resolve => {
        db.query('select  `to`,`is_look`,`id`,`message`,`time` from bilibili_chat where `from`=?', req.user.id, (err, from_res) => {
            if (err) return res.send({
                status: 1,
                message: err
            })
            from_res.forEach((item) => {
                item.is_look = 1
                item.to == req.user.id ? true : ListFrom[item.to] = item
            })
            resolve()
        })
    })

    await new Promise(resolve => {
        db.query('select `from`,`id`,`is_look`, `message`,`time` from bilibili_chat where `to`=?', req.user.id, (err, to_res) => {
            if (err) return res.send({
                status: 1,
                message: err
            })
            to_res.forEach((item) => {
                item.from == req.user.id ? true : ListTo[item.from] = item
            })
            resolve()
        })
    })
    let union = Array.from(new Set([...Object.keys(ListFrom), ...Object.keys(ListTo)]))
    const newArr = union.map((item) => {
        if (ListTo[item] && !ListFrom[item]) {
            ListTo[item].userId = item
            return ListTo[item]
        }
        else if (!ListTo[item] && ListFrom[item]) {
            ListFrom[item].userId = item
            return ListFrom[item]
        }
        else {
            ListFrom[item].userId = item
            ListTo[item].userId = item
            return ListTo[item].id > ListFrom[item].id ? ListTo[item] : ListFrom[item]
        }
    })
    let promiseList = []
    for (let i = 0; i < newArr.length; i++) {
        promiseList.push(new Promise(resolve => {
            db.query('select username,id,profile from bilibili_personal where id=?', newArr[i].userId, (err, here_res) => {
                newArr[i].info = here_res
                resolve()
            })
        }))
    }
    await Promise.all(promiseList)
    res.send({
        status: 0,
        message: newArr
    })
}

exports.getChatNum = (req, res) => {
    db.query('select `is_look` from bilibili_chat where `to` =?', [req.user.id], (err, my_res) => {
        if (err) return res.send({
            status: 1,
            message: err
        })
        let newArr = my_res.filter((item) => !item.is_look)
        res.send({
            status: 0,
            message: newArr.length
        })
    })
}